package com.EAIPClub.codeidedispatchingcenter.service.impl;

import com.api.API.CodeLab.CodeIdeManager.CodeIdeManagerAPI;
import com.api.POJO.CodeLab.CodeIdeDispatchingCenter.CodeIdeDispatchingCenterInfo;
import com.EAIPClub.codeidedispatchingcenter.service.CodeIdeDispatchingCenterService;
import com.api.POJO.CodeLab.CodeIdeManager.CodeIdeUserInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * @Description :CodeIde资源调度业务逻辑实现
 * @Author :崔昌赫
 * @Date : 2021/10/26
 */
@Service
@Slf4j
public class CodeIdeDispatchingCenterServiceImpl implements CodeIdeDispatchingCenterService {

    private CodeIdeManagerAPI managerAPI;

    @Autowired
    public void setManagerAPI(CodeIdeManagerAPI managerAPI) {
        this.managerAPI = managerAPI;
    }

    @SneakyThrows
    @Override
    @RabbitListener(
            bindings = @QueueBinding(
                    value = @Queue(name = "createCodeIde"),
                    exchange = @Exchange(name = "CodelabCreaters"),
                    key = {"createCodeIde"}
            )
    )
    public void createContainer(CodeIdeDispatchingCenterInfo info) {
        log.info("即将开始创建容器.containerName:{},password:{},port:{}",info.getContainerName(),info.getPassword(),info.getPort());
        String createPath = "/bin/sh /root/sh/createorder.sh";
        String cmd = createPath + " " + "codeide" + info.getContainerName() + " " + info.getPort() + " " + info.getPassword();
        log.info("执行命令为:{}",cmd);
        Process exec = Runtime.getRuntime().exec(cmd);
        exec.waitFor();

        String returnInfo1 = getReturnInfo(exec.getInputStream());
        String error1 = getReturnInfo(exec.getErrorStream());
        log.info("执行createorder.sh，结果为:{}",returnInfo1);
        if(returnInfo1.equals("")){
            log.warn("创建容器命令返回为空!返回信息:{}",error1);
            return;
        }

        String node = getNode(info.getContainerName());
        if(node == null){
            log.warn("获取节点失败!");
            return;
        }
        log.info("获取到节点:{}",node);

        info.setNode(node);
        String nodeIp = managerAPI.getNodeIp(node);
        if(nodeIp==null){
            log.warn("获取节点ip失败!");
            return;
        }
        log.info("获取到节点ip:{}",nodeIp);

        info.setAddr(nodeIp);
        Boolean addproxy= createUserLocation(info);
        if(!addproxy){
            log.warn("增加用户反向代理失败!");
            return;
        }

        info.setNode(node);
        log.info("即将将用户容器信息存入到数据库.");
        managerAPI.setCodeIdeUserInfo(new CodeIdeUserInfo(info.getUid(),info.getLocation(),info.getContainerId(),info.getNode(),info.getPort()));
        log.info("容器创建成功!返回信息:{}",returnInfo1);
    }

    @SneakyThrows
    public Boolean createUserLocation(CodeIdeDispatchingCenterInfo info) {
        String location = info.getLocation();
        String addr = info.getAddr()+":"+info.getPort()+"/";
        log.info("即将开始创建用户路径.location:{},addr:{}",location,addr);
        String createLocationPath = "/bin/sh /root/sh/addproxy.sh";
        String cmd = createLocationPath + " " + location + " " + addr;
        log.info("执行命令为:{}",cmd);
        Process exec = Runtime.getRuntime().exec(cmd);
        exec.waitFor();
        String returnInfo = getReturnInfo(exec.getInputStream());
        String error = getReturnInfo(exec.getErrorStream());
        if(returnInfo.equals("")){
            log.warn("增加用户反向代理失败!返回信息:{},location:{},addr:{}",error,location,addr);
            return false;
        }
        log.info("增加用户反向代理成功!返回信息:{},location:{},addr:{}",returnInfo,location,addr);
        return true;
    }

    @SneakyThrows
    private String getReturnInfo(InputStream inputStream){

        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line).append("\n");
        }
        return sb.toString();
    }
    
    @SneakyThrows
    private String getNode(String containerName){
        log.info("即将通过容器id查询节点.containerName:{}",containerName);
        String getNodePath="/bin/sh /root/sh/getnode.sh";
        String cmd = getNodePath + " " +containerName;
        log.info("执行命令为:{},",cmd);
        Process exec = Runtime.getRuntime().exec(cmd);
        exec.waitFor();
        String returnInfo = getReturnInfo(exec.getInputStream());
        String error = getReturnInfo(exec.getErrorStream());
        if(returnInfo.equals("")){
            log.warn("查询容器所在节点失败!返回值:{},错误返回值:{}",returnInfo,error);
            return null;
        }
        return returnInfo.split("\n")[0];
    }
}
